# Based on Arduino example by Jim Lindblom
# http://bildr.org/2011/05/mpr121_arduino/
# https://github.com/scottgarner/BeetBox/blob/master/mpr121.py
# intended to work with the mpr121 cap touchpad from sparkfun
# 3.3V device, I2C, default address 0x5A
# uses an interrupt line, default gpio 25
import smbus
import argparse
# test code taken from http://raspi.tv/2013/how-to-use-interrupts-with-python-on-the-raspberry-pi-and-rpi-gpio 
import RPi.GPIO as GPIO  

    # MPR121 Register Defines
    
MHD_R = 0x2B
NHD_R = 0x2C
NCL_R = 0x2D
FDL_R = 0x2E
MHD_F = 0x2F
NHD_F = 0x30
NCL_F = 0x31
FDL_F = 0x32
ELE0_T = 0x41
ELE0_R = 0x42
ELE1_T = 0x43
ELE1_R = 0x44
ELE2_T = 0x45
ELE2_R = 0x46
ELE3_T = 0x47
ELE3_R = 0x48
ELE4_T = 0x49
ELE4_R = 0x4A
ELE5_T = 0x4B
ELE5_R = 0x4C
ELE6_T = 0x4D
ELE6_R = 0x4E
ELE7_T = 0x4F
ELE7_R = 0x50
ELE8_T = 0x51
ELE8_R = 0x52
ELE9_T = 0x53
ELE9_R = 0x54
ELE10_T = 0x55
ELE10_R = 0x56
ELE11_T = 0x57
ELE11_R = 0x58
FIL_CFG = 0x5D
ELE_CFG = 0x5E
GPIO_CTRL0 = 0x73
GPIO_CTRL1 = 0x74
GPIO_DATA = 0x75
GPIO_DIR = 0x76
GPIO_EN = 0x77
GPIO_SET = 0x78
GPIO_CLEAR = 0x79
GPIO_TOGGLE = 0x7A
ATO_CFG0 = 0x7B
ATO_CFGU = 0x7D
ATO_CFGL = 0x7E
ATO_CFGT = 0x7F

# Global Constants

TOU_THRESH = 0x06
REL_THRESH = 0x0A


class mpr121:
    bus = smbus.SMBus(1)
    
    def readData(self):
        results = mpr121.bus.read_i2c_block_data(self.address, 0x00, 2)
        #print results
        # strangely, below doesn't work? not sure why
        #MSB = mpr121.bus.read_byte_data(self.address, 0x00)
        #LSB = mpr121.bus.read_byte_data(self.address, 0x01)
        #print LSB, MSB
        touchData = (results[1] << 8) | results[0]
        #touchData = MSB;
    
        return touchData;
    def __del__(self):
        GPIO.cleanup()
        
    def __init__(self, address,irq_pin):
        self.address = address
        self.irq_pin = irq_pin
        mpr121.bus.write_byte_data(address, ELE_CFG, 0x00)
    
        # Section A - Controls filtering when data is > baseline.
    
        mpr121.bus.write_byte_data(address, MHD_R, 0x01)
        mpr121.bus.write_byte_data(address, NHD_R, 0x01)
        mpr121.bus.write_byte_data(address, NCL_R, 0x00)
        mpr121.bus.write_byte_data(address, FDL_R, 0x00)
    
        # Section B - Controls filtering when data is < baseline.
    
        mpr121.bus.write_byte_data(address, MHD_F, 0x01)
        mpr121.bus.write_byte_data(address, NHD_F, 0x01)
        mpr121.bus.write_byte_data(address, NCL_F, 0xFF)
        mpr121.bus.write_byte_data(address, FDL_F, 0x02)    
    
        #Section C - Sets touch and release thresholds for each electrode
    
        mpr121.bus.write_byte_data(address, ELE0_T, TOU_THRESH)
        mpr121.bus.write_byte_data(address, ELE0_R, REL_THRESH)
    
        mpr121.bus.write_byte_data(address, ELE1_T, TOU_THRESH)
        mpr121.bus.write_byte_data(address, ELE1_R, REL_THRESH)
    
        mpr121.bus.write_byte_data(address, ELE2_T, TOU_THRESH)
        mpr121.bus.write_byte_data(address, ELE2_R, REL_THRESH)
    
        mpr121.bus.write_byte_data(address, ELE3_T, TOU_THRESH)
        mpr121.bus.write_byte_data(address, ELE3_R, REL_THRESH)
    
        mpr121.bus.write_byte_data(address, ELE4_T, TOU_THRESH)
        mpr121.bus.write_byte_data(address, ELE4_R, REL_THRESH)
    
        mpr121.bus.write_byte_data(address, ELE5_T, TOU_THRESH)
        mpr121.bus.write_byte_data(address, ELE5_R, REL_THRESH)
    
        mpr121.bus.write_byte_data(address, ELE6_T, TOU_THRESH)
        mpr121.bus.write_byte_data(address, ELE6_R, REL_THRESH)
    
        mpr121.bus.write_byte_data(address, ELE7_T, TOU_THRESH)
        mpr121.bus.write_byte_data(address, ELE7_R, REL_THRESH)
    
        mpr121.bus.write_byte_data(address, ELE8_T, TOU_THRESH)
        mpr121.bus.write_byte_data(address, ELE8_R, REL_THRESH)
    
        mpr121.bus.write_byte_data(address, ELE9_T, TOU_THRESH)
        mpr121.bus.write_byte_data(address, ELE9_R, REL_THRESH)
    
        mpr121.bus.write_byte_data(address, ELE10_T, TOU_THRESH)
        mpr121.bus.write_byte_data(address, ELE10_R, REL_THRESH)
    
        mpr121.bus.write_byte_data(address, ELE11_T, TOU_THRESH)
        mpr121.bus.write_byte_data(address, ELE11_R, REL_THRESH)    
    
        # Section D
        # Set the Filter Configuration
        # Set ESI2
    
        mpr121.bus.write_byte_data(address, FIL_CFG, 0x04)
    
        # Section E
        # Electrode Configuration
        # Set ELE_CFG to 0x00 to return to standby mode
    
        mpr121.bus.write_byte_data(address, ELE_CFG, 0x0C)  # Enables all 12 Electrodes

        GPIO.setmode(GPIO.BCM)  
        # GPIO MPR121_IRQ_PIN set up as input. It is pulled up to stop false signals  
        GPIO.setup(irq_pin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
          
    def wait(self):
        GPIO.wait_for_edge(self.irq_pin, GPIO.FALLING)
        
        
def main(i2c_addr,MPR121_IRQ_PIN):

    my_mpr121 = mpr121(i2c_addr,MPR121_IRQ_PIN)
      
      
    print "Make sure you have the irq connected so that when pressed"  
    print "it will connect GPIO port 25 \n"  
    #raw_input("Press Enter when ready\n>")  
      
    print "Waiting for falling edge on port MPR121_IRQ_PIN"  
    # now the program will do nothing until the signal on port 23   
    # starts to fall towards zero. This is why we used the pullup  
    # to keep the signal high and prevent a false interrupt  
      
    print "During this waiting time, your computer is not"   
    print "wasting resources by polling for a button press.\n"  
    print "Press your button when ready to initiate a falling edge interrupt."
    while True:  
        try:  
            my_mpr121.wait()
            # falling edge detected  
            touchData = my_mpr121.readData()
            print( 'Pin ' + str(touchData) + ' was just touched')
        except KeyboardInterrupt:  
            print 'stopped'       # clean up GPIO on CTRL+C exit  

# use opt parse to get command line args
if __name__ == "__main__":
    parser = argparse.ArgumentParser(description='test the mp121 cap touchpad.')
    parser.add_argument('--addr', dest='address', type=int, default=0x5a,
                       help='address of mp121 on i2c bus, default = 0x5a')
    
    parser.add_argument('--irqPin', dest='irqPin', type=int, default=25,
                       help='pin number of the irq line, default = 25')
    
    args = parser.parse_args()
    print 'I2C address is 0x%X' % args.address
    main(args.address, args.irqPin)
        